package panda.natalia.gothread.suspend.instrument.codesample;

/**
 * a simple framework of java fiber
 *
 * @Author: scpanda2007
 * @Date: 2019/12/3 10:30
 *
 * // class version 52.0 (52)
 * // access flags 0x21
 * public class panda/natalia/gothread/suspend/instrument/codesample/TestLambda {
 *
 *   // compiled from: TestLambda.java
 *   // access flags 0x608
 *   static abstract INNERCLASS panda/natalia/gothread/suspend/instrument/codesample/TestLambda$TestMethod panda/natalia/gothread/suspend/instrument/codesample/TestLambda TestMethod
 *   // access flags 0x19
 *   public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup java/lang/invoke/MethodHandles Lookup
 *
 *   // access flags 0x1
 *   public <init>()V
 *    L0
 *     LINENUMBER 9 L0
 *     ALOAD 0
 *     INVOKESPECIAL java/lang/Object.<init> ()V
 *     RETURN
 *    L1
 *     LOCALVARIABLE this Lpanda/natalia/gothread/suspend/instrument/codesample/TestLambda; L0 L1 0
 *     MAXSTACK = 1
 *     MAXLOCALS = 1
 *
 *   // access flags 0x1
 *   public println()Ljava/lang/String;
 *    L0
 *     LINENUMBER 16 L0
 *     ICONST_0 // 注意 这个地方 istore 1 以及 后面的 iload1 是这个函数里 的 inner 变量, 会传给闭包里面
 *     ISTORE 1
 *    L1
 *     LINENUMBER 17 L1
 *     ILOAD 1
 *     INVOKEDYNAMIC doSomething(I)Lpanda/natalia/gothread/suspend/instrument/codesample/TestLambda$TestMethod; [
 *       // handle kind 0x6 : INVOKESTATIC
 *       java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
 *       // arguments:
 *       (ILjava/lang/String;)Ljava/lang/String;,
 *       // handle kind 0x6 : INVOKESTATIC
 *       panda/natalia/gothread/suspend/instrument/codesample/TestLambda.lambda$println$0(IILjava/lang/String;)Ljava/lang/String;,
 *       (ILjava/lang/String;)Ljava/lang/String;
 *     ] // 这些信息 用于构建一个 动态函数绑定, 同时处理了 传入给闭包的变量, 这里的 Invokedynamic doSomething(I) 而不是 实际的 doSomthing(ILjava/lang/String;) 这个值 应该是指的闭包变量的传入
 *     ASTORE 2
 *    L2
 *     LINENUMBER 20 L2
 *     ALOAD 2
 *     ICONST_5
 *     LDC "xx"
 *     INVOKEINTERFACE panda/natalia/gothread/suspend/instrument/codesample/TestLambda$TestMethod.doSomething (ILjava/lang/String;)Ljava/lang/String; (itf)
 *     ARETURN
 *    L3
 *     LOCALVARIABLE this Lpanda/natalia/gothread/suspend/instrument/codesample/TestLambda; L0 L3 0
 *     LOCALVARIABLE inner I L1 L3 1
 *     LOCALVARIABLE tm Lpanda/natalia/gothread/suspend/instrument/codesample/TestLambda$TestMethod; L2 L3 2
 *     MAXSTACK = 3
 *     MAXLOCALS = 3
 *
 *   // access flags 0x9
 *   public static main([Ljava/lang/String;)V
 *    L0
 *     LINENUMBER 24 L0
 *     LDC "hello"
 *     ASTORE 1
 *    L1
 *     LINENUMBER 25 L1
 *     ALOAD 1
 *     INVOKEDYNAMIC run(Ljava/lang/String;)Ljava/lang/Runnable; [
 *       // handle kind 0x6 : INVOKESTATIC
 *       java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
 *       // arguments:
 *       ()V,
 *       // handle kind 0x6 : INVOKESTATIC
 *       panda/natalia/gothread/suspend/instrument/codesample/TestLambda.lambda$main$1(Ljava/lang/String;)V,
 *       ()V
 *     ]
 *     ASTORE 2
 *    L2
 *     LINENUMBER 26 L2
 *     ALOAD 2
 *     INVOKEINTERFACE java/lang/Runnable.run ()V (itf)
 *    L3
 *     LINENUMBER 27 L3
 *     RETURN
 *    L4
 *     LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
 *     LOCALVARIABLE desc Ljava/lang/String; L1 L4 1
 *     LOCALVARIABLE runnable Ljava/lang/Runnable; L2 L4 2
 *     MAXSTACK = 1
 *     MAXLOCALS = 3
 *
 *   // access flags 0x100A
 *   private static synthetic lambda$main$1(Ljava/lang/String;)V
 *    L0
 *     LINENUMBER 25 L0
 *     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
 *     NEW java/lang/StringBuilder
 *     DUP
 *     INVOKESPECIAL java/lang/StringBuilder.<init> ()V
 *     ALOAD 0
 *     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 *     LDC "something"
 *     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 *     INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
 *     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
 *     RETURN
 *    L1
 *     LOCALVARIABLE desc Ljava/lang/String; L0 L1 0
 *     MAXSTACK = 3
 *     MAXLOCALS = 1
 *
 *   // access flags 0x100A
 *   private static synthetic lambda$println$0(IILjava/lang/String;)Ljava/lang/String;
 *    L0
 *     LINENUMBER 18 L0
 *     NEW java/lang/StringBuilder
 *     DUP
 *     INVOKESPECIAL java/lang/StringBuilder.<init> ()V
 *     ILOAD 0  // 注意 这里这个值 就是闭包变量, 此时作为一个传入的参数在这里表示
 *     ILOAD 1
 *     IADD
 *     INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
 *     LDC "b"
 *     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 *     ALOAD 2
 *     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 *     INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
 *     ARETURN
 *    L1
 *     LOCALVARIABLE inner I L0 L1 0
 *     LOCALVARIABLE a I L0 L1 1
 *     LOCALVARIABLE c Ljava/lang/String; L0 L1 2
 *     MAXSTACK = 3
 *     MAXLOCALS = 3
 * }
 *
 * 根据以上代码可以看出 invokedynamic 的意思(TODO: 具体需要再看一下虚拟机规范) 就是生成一个
 *              *  动态函数绑定点
 *                INVOKEDYNAMIC run(Ljava/lang/String;)Ljava/lang/Runnable; [
 *                                   // handle kind 0x6 : INVOKESTATIC
 *                                   java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
 *                                   // arguments:
 *                                   ()V,
 *                                   // handle kind 0x6 : INVOKESTATIC
 *                                   panda/natalia/gothread/suspend/instrument/codesample/TestLambda.lambda$main$0(Ljava/lang/String;)V,
 *                                   ()V
 *                                 ]
 *
 * 查看 doSomething 可以看到更加明显的现象
 *  我们可以看到 java/lang/invoke/LambdaMetafactory 这个类, 不确定owner的判定是否是指的这个 需要再用asm 进行测试
 *
 */
public class TestLambda {

    static interface TestMethod {
        String doSomething(int i, String arg);
    }

    public String println(){
        int inner = 0;
        TestMethod tm = (a, c) -> {
            return inner + a + "b" + c;
        };
        return tm.doSomething(5, "xx");
    }

    public static void main(String[] args) {
        String desc = "hello";
        Runnable runnable = () -> System.out.println(desc + "something");
        runnable.run();
    }
}
